import java.util.Random;

// Tabs = 4
//************************************************************
//	COPYRIGHT 2011 Bread Zeppelin - ALL RIGHTS RESERVED
//
// This file is the product of Bread Zeppelin and cannot be 
// reproduced, copied, or used in any shape or form without 
// the express written consent of Bread Zeppelin.
//************************************************************
//
//	$ID: Concurrent_Assg6
//
//	$Date: Feb 13, 2012
//
//	Reason:
//
//*************************************************************

/** $Author: Ben Hare, Zach Huenink, Philipp Wittmaack, Peter Maresca */
/** $Revision: 1 */

// Default Package

/**
 * Simulator class, creates the restaurant, and customer party classes.
 */
public class Simulator {

	private CustomerPartyFactory customerFactory;
	private Restaurant restaurant;
	public static int simulationSpeed = 1;

	/**
	 * Constructor for Simulator takes two integers for arguments.
	 * @param numTables
	 * @param numHostess
	 */
	Simulator() {
		this.restaurant = Restaurant.getInstance();
		this.customerFactory = new CustomerPartyFactory();
		RestaurantMetrics.getInstance();
	}

	/**
	* Returns an instance of Restaurant.
 	* @return restaurant - the restaurant
 	*/
	public Restaurant getRestaurant() {
		return restaurant;
	}
	
	/**
	 * Sets the passed in Restaurant to restaurant.
	 * @param restaurant
	 */
	public void setRestaurant(Restaurant restaurant) {
		this.restaurant = restaurant;
	}
	
	/**
	* Returns an instance of customerFactory.
 	* @return
 	*/
	public CustomerPartyFactory getCustomerFactory() {
		return customerFactory;
	}
	
	/**
	* Takes in an instance of customerFactory and sets it to customerFactory.
 	* @param customerFactory
 	*/
	public void setCustomerFactory(CustomerPartyFactory customerFactory) {
		this.customerFactory = customerFactory;
	}
	
	/**
	* Main of the program.
 	* @param args
 	*/
	public static void main(String[] args) {
	
		 // Creates a simulator object with the appropriate integers set from
		 // user input.
		 
		Simulator simulator = new Simulator();
		
		simulationSpeed = simulator.getRestaurant().getSimSpeed();
		
		Random numberGen = new Random();
		/**
		 * While loop that creates a new party, then adds it to the
		 * restaurant which triggers a task being created. This action
		 * is completed every t seconds which is determined by the 
		 * simulation speed variable.
		 */
		int numLoops = 0;
		while (true) {
			
			CustomerParty newParty = simulator.getCustomerFactory().createCustomerParty();
				simulator.getRestaurant().addCustomer(newParty);
			
			// Waits up-to 2min before looping back a new customer
			int t = numberGen.nextInt(60000);
			try {Thread.sleep((t + 60000)/Simulator.simulationSpeed);} 
			catch (InterruptedException e) {e.printStackTrace();}
			
			if(numLoops > 100){
				System.out.println("DOORS are Closing");
				break;
			} else {
				numLoops++;
			}
			
		}
		
		while (true) {
			
			if ( Restaurant.getInstance().isClosed() ) {
				System.out.println("People in WaitingList: " + Restaurant.getInstance().getWaitingList().size() );
				System.out.println("Tables in TablePool: " + Restaurant.getInstance().getTablePool().size() );
				break;
			}
			
			try {Thread.sleep(1000);} 
			catch (InterruptedException e) {e.printStackTrace();}
			
		}
		
		// TODO Write to FILE
		File_Writter fw = new File_Writter("Metrics_log");
			fw.addLine("Average Idle Time :: Hostess : " + RestaurantMetrics.getInstance().print_hostessIdleAverage());
			fw.addLine("Average Idle Time :: Waitress : " + RestaurantMetrics.getInstance().print_waitressIdleAverage());
			fw.addLine("Average Idle Time :: Cook : " + RestaurantMetrics.getInstance().print_cookIdleAverage());
			fw.addLine("Average Idle Time :: Food Runner : " + RestaurantMetrics.getInstance().print_foodRunnerAverage());
			fw.addLine("Average Wait Time :: Waiting List : " + RestaurantMetrics.getInstance().print_waitTimeAverage());
			fw.addLine("Average Wait Time :: Seating to Order : " + RestaurantMetrics.getInstance().print_waitingToOrderAverage());
			fw.addLine("Average Wait Time :: Order to Delivery : " + RestaurantMetrics.getInstance().print_fromOrderToDeliveryAverage());
			fw.addLine("Average Seating Time : " + RestaurantMetrics.getInstance().print_seatTimeAverage());
			fw.addLine("Average Cook Time : " + RestaurantMetrics.getInstance().print_cookTimeAverage());
			fw.addLine("Average Customer Time : " + RestaurantMetrics.getInstance().print_customerTimeAverage());
		fw.writeFile();
		
		System.out.println("Restaurant is CLOSED.");
	}
	
	/**
	 * Sets the simulationSpeed variable to timeScaler which is a user input.
	 * @param timeScaler
	 */
	public void setSimulationSpeed(int timeScaler) {
		Simulator.simulationSpeed = timeScaler;
	}
}
